
#include "nane/WindowSystem/Win32/Win32WindowSystem.h"
#include "nane/WindowSystem/Win32/Win32Window.h"
#include "nane/core/log.h"

namespace nane
{
    ////////////////////////////////////////////////////////////////////////////////////////////////
    static LRESULT CALLBACK s_wndProc( HWND _hWnd, UINT _msg, WPARAM _wParam, LPARAM _lParam )
    {
        Win32Window* window = reinterpret_cast<Win32Window*>(WinAPI::GetWindowLongPtr(_hWnd, GWLP_USERDATA));
        if( window != NULL )
            return window->WindowProc(_msg, _wParam, _lParam);
        return WinAPI::DefWindowProc(_hWnd, _msg, _wParam, _lParam);
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////
    Win32WindowSystem::Win32WindowSystem()
        : m_windowClassAtom( 0 )
        , m_hInstance( NULL )
    {
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////
    Win32WindowSystem::~Win32WindowSystem()
    {
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////
    bool Win32WindowSystem::Initialize()
    {
        m_hInstance = ::GetModuleHandle(NULL);
        m_windowClassAtom = WinAPI::RegisterClass("NANEWindowClass", m_hInstance, &s_wndProc);
        return (m_windowClassAtom != 0) && (m_hInstance != 0);
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////
    void Win32WindowSystem::Shutdown()
    {
        WinAPI::UnregisterClass(m_windowClassAtom, m_hInstance);
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////
    IWindow* Win32WindowSystem::CreateWindow( const char* _title, uint32 _width, uint32 _height, uint32 _posX, uint32 _posY )
    {
        NANE_ASSERT( (m_windowClassAtom != 0) && (m_hInstance != 0), "WindowSystem must be intitialized" );
        Win32Window* window = NULL;

        RECT windowRect;
        windowRect.top = 0;
        windowRect.left = 0;
        windowRect.bottom = _height;
        windowRect.right = _width;
        ::AdjustWindowRect(&windowRect, WS_OVERLAPPEDWINDOW, FALSE);

        HWND hWnd = WinAPI::CreateWindow(m_windowClassAtom, _title, WS_OVERLAPPEDWINDOW, static_cast<int>(_posX), static_cast<int>(_posY)
                                        , static_cast<int>(windowRect.right), static_cast<int>(windowRect.bottom), NULL, NULL, m_hInstance, NULL);
        if( hWnd != NULL )
        {
            window = new Win32Window(hWnd);
        }
        else
        {
            // TODO: add error message logging
        }
        return window;
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////
    void Win32WindowSystem::ReleaseWindow( IWindow* _window )
    {
        Win32Window* win32Window = static_cast<Win32Window*>(_window);
        if( win32Window != NULL )
        {
            HWND hWnd = static_cast<HWND>(win32Window->GetOSHandle());
            delete win32Window;
            ::DestroyWindow(hWnd);
        }
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////
    uint32 Win32WindowSystem::GetScreenWidth()
    {
        return static_cast<uint32>(::GetSystemMetrics(SM_CXSCREEN));
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////
    uint32 Win32WindowSystem::GetScreenHeight()
    {
        return static_cast<uint32>(::GetSystemMetrics(SM_CYSCREEN));
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////
}   // namespace nane
